﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TAS;
using OMS;
using System.Threading;
using System.IO;
using FIXForge.NET.FIX;
using Algo;

namespace ProbeStation
{
    using FIXForge.NET.FIX.FAST;

    class Program
    {
        protected static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public static List<OrderBookEntity> CLM2OrderBook = new List<OrderBookEntity>();
        public static List<OrderBookEntity> CLN2OrderBook = new List<OrderBookEntity>();
        public static List<OrderBookEntity> CLM2CLN2OrderBook = new List<OrderBookEntity>();

        static void Main(string[] args)
        {
            bool encode = false;

            //log.Info("Hello World. This is Probe, your friendly unit tester");

            EngineSettings settings = new EngineSettings();

            // use Dialect.xml to Encode, FixDialectDescription.xml for Handler

            if (encode == true)
            {
                settings.Dialect = "Dialect.xml"; 
            }
            else
            {
                settings.Dialect = "FixDialectDescription.xml";
            }

            settings.LogDirectory = "\\Logs";
            Engine.Init(settings);

            if (encode == true)
            {
                //List<string> securityList = new List<string>();
                //securityList.Add("CLG3-CLJ3");
                //GenerateSnapshotMessage(securityList, 10, 30, 0);

                List<string> filenames = new List<string>();
                filenames.Add("SecurityDefinitions.txt");
                filenames.Add("IncrementalRefresh.txt");
                Encode(filenames);

                //FeedCMEFutureData();
            }
            else
            {
               // TASProbe();

                //added by MS
                
                AlgoProbe();
            }
           
            //log.Info("Bye, Shutting Down");
        }

        static void AlgoProbe()
        {
            AlgoEngine algoEngine = new AlgoEngine();
            algoEngine.Initialize();

            Console.ReadLine();
        }

        static void OMSProbe()
        {
            OMSEngine engine = new OMSEngine();
            engine.Initialize();
            engine.Connect();
            //engine.Buy("MSFT", 102, 100); - to be modified
            Thread.Sleep(1000);
        }

        static void TASProbe()
        {
            TASEngine engine = new TASEngine();
            engine.Initialize();

           /* while (true)
            {
                Thread.Sleep(0);
            }*/
        }

        public static void FeedCMEFutureData()
        {
            try
            {
                // use Dialect.xml in line 28
                string[] filenames = { "XNYM_CL_CL_FUT_20120902.txt", "XNYM_CL_CL_FUT_SPD_20120902.txt" };

                List<CMEFutureData> fixMessages = new List<CMEFutureData>();

                bool allFilesRead = false;

                foreach (string filename in filenames)
                {
                    CMEFutureData cmeFutureData = new CMEFutureData();
                    cmeFutureData.Initialize(filename);

                    FixMessageEntity fixMessage = null;
                    fixMessage = cmeFutureData.ReadData();
                    fixMessages.Add(cmeFutureData);
                }

                using (StreamWriter writer = new StreamWriter("CLV2_CLX2_CLV2CLX2.txt", false))
                {
                    while (allFilesRead == false)
                    {
                        Thread.Sleep(0);

                        CMEFutureData smallest = fixMessages.First();

                        foreach (CMEFutureData item in fixMessages)
                        {
                            if (smallest.EndofFile == true)
                            {
                                if (item.EndofFile == true)
                                {
                                    break;
                                }
                                else
                                {
                                    smallest = item;
                                }
                            }
                            else if (item.EndofFile == true && smallest.EndofFile == false)
                            {
                                // do nothing
                            }
                            else if (smallest.fixMessageEntity.SendingTime > item.fixMessageEntity.SendingTime)
                            {
                                smallest = item;
                            }
                        }

                        if (smallest.fixMessageEntity.FixMessage.Contains("=CLV2" + (char)0x01) ||
                             smallest.fixMessageEntity.FixMessage.Contains("=CLX2" + (char)0x01) ||
                             smallest.fixMessageEntity.FixMessage.Contains("=CLV2-CLX2" + (char)0x01))
                        {
                            writer.WriteLine(smallest.fixMessageEntity.FixMessage);
                            writer.Flush();
                        }

                        smallest.ReadData();
                        allFilesRead = true;

                        foreach (var item in fixMessages)
                        {
                            if (item.EndofFile == false)
                            {
                                allFilesRead = false;
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //log.Error("Exception : ", ex);
            }
        }

        static void Encode(List<string> files)
        {
            try
            {
                Logger logger = new Logger();
                logger.Initialize("ModifiedFix.txt");

                string xmlFastTemplate = System.IO.File.ReadAllText("templates.xml");

                int incrementalMsgCount = 1;

                const bool encodeEachMessageIndependently = true;
                Encoder encoder = new Encoder(xmlFastTemplate, ProtocolVersion.FIX44, encodeEachMessageIndependently);

                string channelId = "30";

                string format = "{0} [{1}] Repository: {2}: Packet received ({3}).";

                using (StreamWriter writer = new StreamWriter("Sample//log.txt", false))
                {
                    foreach (string file in files)
                    {
                        string[] fileContents = System.IO.File.ReadAllLines(file);

                        foreach (var line in fileContents)
                        {
                            if (string.IsNullOrEmpty(line))
                                continue;

                            string textMessage;
                            if (!line.StartsWith("8="))
                            {
                                textMessage =
                                    "8=FIXT.1.1" + (char)0x01 + // prefix
                                    "9=" + line.Length + (char)0x01 + // message length
                                    "35=X" + (char)0x01 + // message type
                                    line;
                            }
                            else
                            {
                                textMessage = line;
                            }

                            Message sourceFixMessage = Message.Parse(textMessage, new Dialect("CME"));

                            string feedName;
                            switch (sourceFixMessage.Type)
                            {
                                case "d":
                                    feedName = "InstrumentFeedGroup";

                                    if (!sourceFixMessage.Contain(911))
                                    {
                                        sourceFixMessage.Set(911, fileContents.Length);
                                    }

                                    break;
                                case "W":
                                    feedName = "SnapshotFeedGroup";

                                    if (!sourceFixMessage.Contain(911))
                                    {
                                        //sourceFixMessage.Set(911, fileContents.Length);
                                        sourceFixMessage.Set(911, 5);
                                    }

                                    if (!sourceFixMessage.Contain(83))
                                    {
                                        //sourceFixMessage.Set(83, fileContents.Length);
                                        sourceFixMessage.Set(83, 5);
                                    }

                                    break;
                                default:
                                case "X":
                                    feedName = "IncrementalFeedGroup";

                                    if (!sourceFixMessage.Contain(75))
                                    {
                                        sourceFixMessage.Set(75, "20120902");
                                    }

                                    sourceFixMessage.Set(34, incrementalMsgCount++);

                                    break;
                            }

                            logger.Log(sourceFixMessage.ToString());

                            byte[] fastStreamChunk = encoder.Encode(sourceFixMessage);

                            byte[] buffer = new byte[fastStreamChunk.Length + 5];
                            ToBuffer(sourceFixMessage.SeqNum, buffer, 0);
                            Array.Copy(fastStreamChunk, 0, buffer, 5, fastStreamChunk.Length);

                            string logLine = string.Format(format,
                                DateTime.Now.ToString("yyyyMMdd-HH:mm:ss.fff"),
                                channelId,
                                feedName,
                                Convert.ToBase64String(buffer));

                            logLine = logLine + (char)0x01;

                            writer.WriteLine(logLine);
                        }
                        writer.Flush();
                    }
                }

                logger.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        static void ToBuffer(int value, byte[] buffer, int offset)
        {
            uint uValue = (uint)value;
            buffer[0 + offset] = (byte)(uValue >> 24);
            buffer[1 + offset] = (byte)(uValue >> 16);
            buffer[2 + offset] = (byte)(uValue >> 8);
            buffer[3 + offset] = (byte)(uValue);
        }

        static void GenerateSnapshotMessage(List<string> securityList, int startPrice, int endPrice, int quantity)
        {
            Logger logger = new Logger();
            logger.Initialize("CLG3-CLJ3 - Snapshot.txt");

            string snapshot = "8=FIXT.1.1" + (char)0x01, data = string.Empty;
            int sequenceNumber = 1; // random value, pls set accordingly

            foreach (string securityID in securityList)
            {
                for (int price = startPrice; price <= endPrice; price = price + 5)
                {
                    data = String.Empty;
                    data = data + "269=0" + (char)0x01 + "270=" + price + (char)0x01 + "271=" + quantity + (char)0x01;
                    data = data + "269=1" + (char)0x01 + "270=" + price + (char)0x01 + "271=" + quantity + (char)0x01;
                    data = data + "269=2" + (char)0x01 + "270=" + price + (char)0x01 + "271=" + quantity + (char)0x01;

                    string dateTime = "" + DateTime.Now.Year + "" + DateTime.Now.Day + "" + (DateTime.Now.Month + 1);
                    dateTime = dateTime + "" + DateTime.Now.Hour + "" + DateTime.Now.Minute + "" + DateTime.Now.Second + "" + DateTime.Now.Millisecond;

                    string fixmessage = "8=FIXT.1.1" + (char)0x01 + "9=" + data.Length + (char)0x01 + "35=W" + (char)0x01;
                    fixmessage = fixmessage + "49=CME" + (char)0x01 + "56=VSY" + (char)0x01 + "34=" + sequenceNumber + (char)0x01;
                    fixmessage = fixmessage + "48=122" + (char)0x01 + "22=123" + (char)0x01;
                    fixmessage = fixmessage + "52=" + dateTime + (char)0x01 + "369=19" + (char)0x01 + "1021=2" + (char)0x01;
                    fixmessage = fixmessage + "55=CME" + (char)0x01 + "1128=9" + (char)0x01 + "268=3" + (char)0x01;
                    fixmessage = fixmessage + data;

                    try
                    {
                        Message fix = new Message(fixmessage);
                        fix.UpdateCheckSum();
                        fix.Validate();

                        logger.Log(fix.ToString());
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }

                }
            }

            logger.Close();
        }
    }
}
